<?php
declare (strict_types = 1);

namespace app\frontend\controller;

use app\frontend\model\RequirementContent;
use app\frontend\model\UserProject;
use think\facade\Db;
use think\facade\Filesystem;
use think\facade\Validate;

class Requirement extends Base
{
    // 需求列表页
    public function index()
    {
        // 找出当前用户所属的所有项目
        $userInfo = session('userInfo');
        $projectIds = UserProject::field('id,project_id')
            ->where('user_id', $userInfo['id'])
            ->column('project_id');
        $projects = \app\frontend\model\Project::field('id,name')->select($projectIds)->toArray();

        return view('', [
            'projects' => $projects
        ]);
    }

    // 需求列表数据接口
    public function list()
    {
        $page = request()->param('page');
        $limit = request()->param('limit');
        $project = request()->param('project');
        $status = request()->param('status');
        $name = request()->param('name');

        if ($status == 'all') {
            $status = [1, 2, 3, 4];
        } else {
            $status = [$status];
        }

        $userInfo = session('userInfo');
        if ($project == 'all') {
            $requirementList = \app\frontend\model\Requirement::with(['project'])
                ->field('id,project_id,name,start_time,end_time,status,priority')
                ->where('user_id', $userInfo['id'])
                ->where([
                    ['name', 'like', '%'.$name.'%'],
                    ['status', 'in', $status],
                    ['pid', '=', 0]
                ])
                ->order('id', 'desc')
                ->paginate([
                    'list_rows' => $limit,
                    'var_page' => 'page',
                    'page' => $page,
                    'query' => [
                        'name' => $name,
                        'status' => $status
                    ]
                ]);
        } else {
            $requirementList = \app\frontend\model\Requirement::with(['project'])
                ->field('id,project_id,name,start_time,end_time,status,priority')
                ->where('user_id', $userInfo['id'])
                ->where([
                    ['name', 'like', '%'.$name.'%'],
                    ['project_id', '=', $project],
                    ['status', 'in', $status],
                    ['pid', '=', 0]
                ])
                ->order('id', 'desc')
                ->paginate([
                    'list_rows' => $limit,
                    'var_page' => 'page',
                    'page' => $page,
                    'query' => [
                        'name' => $name,
                        'project_id' => $project,
                        'status' => $status
                    ]
                ]);
        }

        $requirementListData = $requirementList->toArray()['data'];
        foreach ($requirementListData as &$requirement) {
            $requirement['project'] = $requirement['project']['name'];
            $requirement['start_time'] = date('Y-m-d H:i:s', $requirement['start_time']);
            $requirement['end_time'] = date('Y-m-d H:i:s', $requirement['end_time']);
        }

        $data = [
            'code' => 0,
            'msg' => '',
            'count' => $requirementList->total(),
            'data' => $requirementListData
        ];

        return json($data);
    }

    // 需求添加页
    public function add()
    {
        // 找出当前用户所属的所有项目
        $userInfo = session('userInfo');
        $projectIds = UserProject::field('id,project_id')
            ->where('user_id', $userInfo['id'])
            ->column('project_id');
        $projects = \app\frontend\model\Project::field('id,name')->select($projectIds)->toArray();

        return view('', [
            'projects' => $projects
        ]);
    }

    // 富文本编辑器图片上传接口
    public function uploadImg()
    {
        $files = request()->file();
        $saveName = [];
        try {
            validate(['image' => ['fileSize:1024000', 'fileExt:jpg,png,gif,jpeg']])
                ->check($files);
            $ds = DIRECTORY_SEPARATOR;
            foreach($files as $file) {
                $saveName[] = $ds.'uploads'.$ds . Filesystem::disk('public')->putFile('image'.$ds.'temp', $file);
            }
        } catch (\think\exception\ValidateException $e) {
            return json([
                'errno' => 1,
                'data' => $e->getMessage()
            ]);
        }

        // 根据操作系统的不同对返回的saveName格式进行处理
        foreach ($saveName as &$v) {
            if ($ds == '/') {
                $v = str_replace('\\', $ds, $v);
            } else {
                $v = str_replace('/', $ds, $v);
            }
        }
        unset($v);

        return json([
            'errno' => 0,
            'data' => $saveName
        ]);
    }

    // 上传附件接口
    /*public function uploadAttachment()
    {
        $file = request()->file('file');
        $saveName = '';
        try {
            validate(['attachment' => ['fileSize:1024000']])
                ->check([$file]);
            $ds = DIRECTORY_SEPARATOR;
            $saveName = $ds.'uploads'.$ds . Filesystem::disk('public')->putFile('attachment'.$ds.'requirement', $file);
        } catch (\think\exception\ValidateException $e) {
            return json([
                'code' => 1,
                'msg' => $e->getMessage(),
                'src' => ''
            ]);
        }

        // 根据操作系统的不同对返回的saveName格式进行处理
        if ($ds == '/') {
            $saveName = str_replace('\\', $ds, $saveName);
        } else {
            $saveName = str_replace('/', $ds, $saveName);
        }

        return json([
            'code' => 0,
            'msg' => '上传成功',
            'src' => $saveName
        ]);
    }*/

    // 保存
    public function save()
    {
        $params['name'] = trim(input('post.name', '', 'strip_tags'));
        $params['project_id'] = trim(input('post.project', '', 'strip_tags'));
        $params['startTime'] = strtotime(trim(input('post.startTime', '', 'strip_tags')));
        $params['endTime'] = strtotime(trim(input('post.endTime', '', 'strip_tags')));
        $params['priority'] = trim(input('post.priority', '', 'strip_tags'));
        $params['content'] = input('post.content', '');
//        $params['attachment'] = input('post.attachment', []);

        $validate = Validate::rule([
            'name|名称' => 'require|max:20',
            'startTime|开始时间' => 'require',
            'endTime|结束时间' => 'require',
            'content|详情描述' => 'max:65535',
            'priority|优先级' => 'require'
        ]);
        if (!$validate->check($params)) {
            return json([
                'code' => 1,
                'msg' => $validate->getError()
            ]);
        }

        // 处理富文本编辑器传来的文本内容
        $newContent = $this->processContent($params['content']);
        $userInfo = session('userInfo');

        // 将数据存入数据库
        Db::startTrans();
        try {
            $requirementModel = \app\frontend\model\Requirement::create([
                'project_id' => $params['project_id'],
                'name' => $params['name'],
                'status' => 1,
                'start_time' => $params['startTime'],
                'end_time' => $params['endTime'],
                'user_id' => $userInfo['id'],
                'priority' => $params['priority'],
                'pid' => 0,
//                'attachment' => implode(',', $params['attachment'])
            ]);
            RequirementContent::create([
                'requirement_id' => $requirementModel->id,
                'content' => htmlspecialchars($newContent)
            ]);

            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            // 返回操作失败信息
            return json([
                'code' => 1,
                'msg' => '保存失败'
            ]);
        }

        return json([
            'code' => 0,
            'msg' => '保存成功'
        ]);
    }

    // 需求查看编辑页
    public function edit()
    {
        // 需求信息
        $id = (int)input('get.id', '', 'strip_tags');
        $requirement = \app\frontend\model\Requirement::field('id,name,project_id,start_time,end_time,status,priority')
            ->find($id);
        $requirement->requirementContent;

        $project = \app\frontend\model\Project::field('id,name')->find($requirement->project_id)->toArray();

        $requirementData = [
            'id' => $id,
            'name' => $requirement['name'],
            'project_id' => $requirement['project_id'],
            'start_time' => $requirement['start_time'],
            'end_time' => $requirement['end_time'],
            'status' => $requirement['status'],
            'priority' => $requirement['priority'],
//            'attachment' => explode(',', $requirement['attachment']),
            'content' => $requirement['requirementContent']['content'],
            'project' => $project['name'],
        ];

        return view('', [
            'requirement' => $requirementData
        ]);
    }

    // 删除附件
    /*public function delAttachment()
    {
        $path = input('post.path', '');
        $id = (int)input('post.id', '', 'strip_tags');

        // 删除图片
        unlink('.'.$path);
        // 更新数据库
        $requirement = \app\frontend\model\Requirement::find($id);
        if (empty($requirement->attachment)) {
            $attachmentArray = [];
        } else {
            $attachmentArray = explode(',', $requirement->attachment);
        }
        foreach ($attachmentArray as $k=>$v) {
            if ($v == $path) {
                unset($attachmentArray[$k]);
            }
        }
        $attachmentString = implode(',', $attachmentArray);
        $requirement->attachment = $attachmentString;
        $requirement->save();

        return json([
            'code' => 0,
            'msg' => '删除成功'
        ]);
    }*/

    // 编辑页面保存接口
    public function update()
    {
        // 需求信息
        $params['id'] = (int)trim(input('post.id', '', 'strip_tags'));
        $params['name'] = trim(input('post.name', '', 'strip_tags'));
        $params['startTime'] = strtotime(trim(input('post.startTime', '', 'strip_tags')));
        $params['endTime'] = strtotime(trim(input('post.endTime', '', 'strip_tags')));
        $params['priority'] = trim(input('post.priority', '', 'strip_tags'));
        $params['content'] = input('post.content', '');
//        $params['attachment'] = input('post.attachment', []);

        // 格式验证
        $validate = Validate::rule([
            'id|id' => 'require|integer',
            'name|名称' => 'require|max:20',
            'startTime|开始时间' => 'require',
            'endTime|结束时间' => 'require',
            'priority|优先级' => 'require'
        ]);
        if (!$validate->check($params)) {
            return json([
                'code' => 1,
                'msg' => $validate->getError()
            ]);
        }

        // 优先级参数设置
        switch ($params['priority']) {
            case '低':
                $params['priority'] = 1;
                break;
            case '中':
                $params['priority'] = 2;
                break;
            case '高':
                $params['priority'] = 3;
                break;
            default:
                return json([
                    'code' => 2,
                    'msg' => '优先级参数错误'
                ]);
        }

        $requirementModel = \app\frontend\model\Requirement::find($params['id']);

        // 附件处理
        /*$attachment = $requirementModel->attachment;
        if (empty($attachment)) {
            $attachmentArray = [];
        } else {
            $attachmentArray = explode(',', $attachment);
        }
        $attachmentArray = array_merge($attachmentArray, $params['attachment']);
        $attachmentString = implode(',', $attachmentArray);*/

        // 富文本内容处理
        // 处理富文本编辑器传来的文本内容
        $newContent = $this->processContent($params['content']);
        // 找到原先content中存在但是富文本编辑器在本次编辑中删除的图片的url，然后删除该图片
        // 找到数据库中存储的content
        $oldContent = RequirementContent::where('requirement_id', $params['id'])->find();
        $oldContent = htmlspecialchars_decode($oldContent['content']);
        // 正则表达式匹配查找图片路径
        $pattern = '/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.jpeg|\.png]))[\'|\"].*?[\/]?>/i';
        preg_match_all($pattern, $oldContent, $oldMatches);
        $oldImgs = $oldMatches[1];
        preg_match_all($pattern, $newContent, $newMatches);
        $newImgs = $newMatches[1];
        // 删除图片
        for ($i=0; $i < count($oldImgs); $i++) {
            if (!in_array($oldImgs[$i], $newImgs)) {
                unlink('.' . $oldImgs[$i]);
            }
        }

        // 将数据存入数据库
        Db::startTrans();
        try {
            // 更新requirement表
            $requirementModel->name = $params['name'];
            $requirementModel->start_time = $params['startTime'];
            $requirementModel->end_time = $params['endTime'];
            $requirementModel->priority = $params['priority'];
//            $requirementModel->attachment = $attachmentString;
            $requirementModel->save();
            // 更新requirement_content表
            $requirementContent = RequirementContent::where('requirement_id', $params['id'])->find();
            $requirementContent->content =htmlspecialchars($newContent);
            $requirementContent->save();

            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            // 返回操作失败信息
            return json([
                'code' => 2,
                'msg' => '修改失败'
            ]);
        }

        return json([
            'code' => 0,
            'msg' => '修改成功'
        ]);
    }

    // 需求生成计划
    public function generate()
    {
        $id = (int)trim(input('post.id', '', 'strip_tags'));

        // 启动事务
        Db::startTrans();
        try {
            $requirementModel = \app\frontend\model\Requirement::find($id);
            $requirementModel->status = 2;
            $requirementModel->save();

            \app\frontend\model\Plan::create([
                'project_id' => $requirementModel->project_id,
                'name' => $requirementModel->name,
                'desc' => '',
                'start_time' => $requirementModel->start_time,
                'end_time' => $requirementModel->end_time,
                'user_id' => $requirementModel->user_id,
                'priority' => $requirementModel->getData('priority'),
                'requirement_id' => $id
            ]);

            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return json([
                'code' => 1,
                'msg' => $e->getMessage()
            ]);
        }

        return json([
            'code' => 0,
            'msg' => '生成成功'
        ]);
    }

    // 生成的计划页面
    public function plan()
    {
        $id = (int)trim(input('get.id', '', 'strip_tags'));

        return view('', [
            'requirementId' => $id
        ]);
    }

    // 需求列表删除接口
    public function delete()
    {
        $id = (int)trim(input('post.id', '', 'strip_tags'));

        // 要先删除所有子需求才能删除该需求
        $subRequirement = \app\frontend\model\Requirement::where('pid', $id)->find();
        if (!empty($subRequirement)) {
            return json([
                'code' => 1,
                'msg' => '要先删除所有子需求才能删除该需求'
            ]);
        }

        // 删除该需求生成的计划下的所有子计划才能删除该需求
        $plan = \app\frontend\model\Plan::where('requirement_id', $id)->find();
        if (!empty($plan)) {
            $subPlan = \app\frontend\model\Plan::where('pid', $plan->id)->find();
            if (!empty($subPlan)) {
                return json([
                    'code' => 2,
                    'msg' => '删除该需求生成的计划下的所有子计划才能删除该需求'
                ]);
            }
        }

        // 启动事务
        Db::startTrans();
        try {
            // 删除生成的计划
            if (!empty($plan)) {
                $plan->delete();
            }
            $requirementModel = \app\frontend\model\Requirement::find($id);
            \app\frontend\model\Requirement::destroy($id);

            $requirementContentModel = RequirementContent::where('requirement_id', $id)->find();
            $content = htmlspecialchars_decode($requirementContentModel->content);
            $requirementContentModel->delete();

            // 删除content中的图片
            $pattern = '/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.jpeg|\.png]))[\'|\"].*?[\/]?>/i';
            preg_match_all($pattern, $content, $matches);
            $images = $matches[1];
            // 删除图片
            for ($i=0; $i < count($images); $i++) {
                unlink('.' . $images[$i]);
            }

            // 删除对应的附件
            /*$attachmentArr = explode(',', $requirementModel->attachment);
            foreach ($attachmentArr as $v) {
                if (!empty($v)) {
                    unlink('.' . $v);
                }
            }*/

            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return json([
                'code' => 2,
                'msg' => $e->getMessage()
            ]);
        }

        return json([
            'code' => 0,
            'msg' => '删除成功'
        ]);
    }

    // 任务列表多选删除接口
    public function deleteMulti()
    {
        $ids = input('post.ids', '', 'strip_tags');

        // 要先删除所有子需求才能删除该需求
        $subRequirements = \app\frontend\model\Requirement::where('pid', 'in', $ids)->select();
        if (!$subRequirements->isEmpty()) {
            return json([
                'code' => 1,
                'msg' => '要先删除所有子需求才能删除该需求'
            ]);
        }

        // 删除该需求生成的计划下的所有子计划才能删除该需求
        $planIds = \app\frontend\model\Plan::where('requirement_id', 'in', $ids)->column('id');
        $subPlan = \app\frontend\model\Plan::where('pid', 'in', $planIds)->find();
        if (!empty($subPlan)) {
            return json([
                'code' => 2,
                'msg' => '删除该需求生成的计划下的所有子计划才能删除该需求'
            ]);
        }

        foreach ($ids as $id) {
            Db::startTrans();
            try {
                $requirementModel = \app\frontend\model\Requirement::find($id);
                \app\frontend\model\Requirement::destroy($id);

                $planModel = \app\frontend\model\Plan::where('requirement_id', $id)->find();
                if (!empty($planModel)) {
                    $planModel->delete();
                }

                $requirementContentModel = RequirementContent::where('requirement_id', $id)->find();
                $content = htmlspecialchars_decode($requirementContentModel->content);
                $requirementContentModel->delete();

                // 删除content中的图片
                $pattern = '/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.jpeg|\.png]))[\'|\"].*?[\/]?>/i';
                preg_match_all($pattern, $content, $matches);
                $images = $matches[1];
                // 删除图片
                for ($i=0; $i < count($images); $i++) {
                    unlink('.' . $images[$i]);
                }

                // 删除对应的附件
                /*$attachmentArr = explode(',', $requirementModel->attachment);
                foreach ($attachmentArr as $v) {
                    if (!empty($v)) {
                        unlink('.' . $v);
                    }
                }*/

                // 提交事务
                Db::commit();
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                // 返回操作失败信息
                return json([
                    'code' => 3,
                    'msg' => $e->getMessage()
                ]);
            }
        }

        return json([
            'code' => 0,
            'msg' => '删除成功'
        ]);
    }

    /**
     * 富文本编辑器文本内容处理
     * @param string $content 富文本编辑器文本内容
     * @return bool|mixed|null 处理的结果
     */
    private function processContent($content)
    {
        // 转移图片
        if (!empty($content)) {
            // 已经存在的图片
            $imgArray = [];
            // 完成处理的content
            $newContent = null;

            $ds = DIRECTORY_SEPARATOR;

            // 正则表达式匹配查找图片路径
            $pattern = '/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.jpeg|\.png]))[\'|\"].*?[\/]?>/i';
            preg_match_all($pattern, $content, $matches);
            $count = count($matches[1]);
            for ($i=0; $i < $count; $i++) {
                $editorImg = $matches[1][$i];
                // 根据操作系统的不同对返回的saveName格式进行处理
                if ($ds == '/') {
                    $editorImg = str_replace('\\', $ds, $editorImg);
                } else {
                    $editorImg = str_replace('/', $ds, $editorImg);
                }
                // 判断是否是新上传的图片
                $position = stripos($editorImg, $ds."temp".$ds);
                if ($position > 0) {    // 新上传的图片走这里
                    // 将图片从临时temp文件夹中迁移到article文件夹中
                    // 传过来的临时文件路径为：/uploads/image/temp/20201030/d885cc3b24b184a7c631408b5e0f670e.jpg
                    // 要迁移的文件路径：/uploads/image/article/20201030/d885cc3b24b184a7c631408b5e0f670e.jpg
                    // 新建日期文件夹
                    $tempArray = explode($ds, $editorImg);
                    $imageFloder = '.'.$ds.'uploads'.$ds.'image'.$ds.'requirement'.$ds . $tempArray[4];
                    if (!is_dir($imageFloder)) {
                        mkdir($imageFloder, 0777, true);
                    }
                    $tempImg = '.' . $editorImg;
                    $newImg = str_replace($ds.'temp'.$ds, $ds.'requirement'.$ds, $tempImg);
                    // 转移图片
                    rename($tempImg, $newImg);
                } else {
                    // 已经存在的图片走这里
                    $imgArray[] = $editorImg;
                }
            }

            // 重新整理content中的图片路径
            $newContent = str_replace($ds.'temp'.$ds, $ds.'requirement'.$ds, $content);
            return $newContent;
        }

        return false;
    }
}
